package task3

import grails.web.JSONBuilder

class OrganizationService {

    final String ORGANIZATION_ID_PREFIX = 'org_'
    final String DEPARTMENT_ID_PREFIX = 'dep_'
    final String PROJECT_ID_PREFIX = 'pro_'
    final String HUMAN_ID_PREFIX = 'hum_'

    final String PROJECT_ICON = 'projectIcon'
    final String DEPARTMENT_ICON = 'departmentIcon'
    final String HUMAN_ICON = 'humanIcon'
    final String ORGANIZATION_ICON = 'organizationIcon'


    def parseInitialTreeToJson() {
        List dep = Department.list()
        def builder = new JSONBuilder()
        def root = builder.build {
            children: dep.collect {
                Department d ->
                    [text: d.name, id: DEPARTMENT_ID_PREFIX + d.id, iconCls: DEPARTMENT_ICON,
                            children: d.projects.collect {
                                Project p ->
                                    [text: p.name, id: PROJECT_ID_PREFIX + p.id, iconCls: PROJECT_ICON,
                                            children: p.people.collect {
                                                Human a -> [text: a.name, id: HUMAN_ID_PREFIX + a.id, iconCls: HUMAN_ICON, leaf: true]
                                            }]
                            }]
            }
        }
        return root.toString()
    }

    def getNodeInDatabase(params) {
        def prefix = params.id.substring(0, params.id.indexOf('_') + 1)
        def receivedId = params.id.substring(params.id.indexOf('_') + 1)

        def objectFound
        switch (prefix) {
            case HUMAN_ID_PREFIX:
                objectFound = Human.get(receivedId as Long)
                break

            case PROJECT_ID_PREFIX:
                objectFound = Project.get(receivedId as Long)
                break

            case DEPARTMENT_ID_PREFIX:
                objectFound = Department.get(receivedId as Long)
                break

            default: objectFound = null
        }
        return objectFound
    }

    def saveHuman(human, params) {
        human.name = params.name
        human.position = params.position
        human.age = !params.age ? null : Integer.parseInt(params.age)
        human.salary = !params.salary ? null : Float.parseFloat(params.salary)
        human.gender = params.gender
        human.humanEmail = params.humanEmail
        human.dateHired = !params.dateHired ? null : Date.parse('M/d/yyyy', params.dateHired)
        if (human.validate()) {
            human.save(flush: true)
        } else {
            human.discard()
        }
    }

    def saveProject(project, params) {
        project.name = params.name
        if (project.validate()) {
            project.save(flush: true)
        } else {
            project.discard()
        }
    }

    def saveDepartment(department, params) {
        department.name = params.name
        if (department.validate()) {
            department.save(flush: true)
        } else {
            department.discard()
        }
    }

    def getErrorMessage(objectFound) {
        def errorsMap = [:]
        objectFound.errors.fieldErrors.each {
            errorsMap.put(it.field, it.code)
        }
        return errorsMap
    }

    def getSuccessMessage() {
        return 'Saved successfully!'
    }

    def getFailureMessage() {
        return 'Not saved!'
    }

    def updateNode(params) {
        def idString = params.id
        def prefix = idString.substring(0, idString.indexOf('_') + 1)
        def receivedId = idString.substring(idString.indexOf('_') + 1)

        def objectFound = null

        switch (prefix) {
            case HUMAN_ID_PREFIX:
                objectFound = Human.get(receivedId as Long)
                if (objectFound) {
                    saveHuman(objectFound, params)
                }
                break

            case PROJECT_ID_PREFIX:
                objectFound = Project.get(receivedId as Long)
                if (objectFound) {
                    saveProject(objectFound, params)
                }
                break

            case DEPARTMENT_ID_PREFIX:
                objectFound = Department.get(receivedId as Long)


                if (objectFound) {
                    saveDepartment(objectFound, params)
                }
                break
        }

        if (objectFound.hasErrors()) {

            return [success: false, errors: getErrorMessage(objectFound), msg: getFailureMessage()]
        } else {
            return [success: true, msg: getSuccessMessage()]
        }
    }


    def saveNewNode(params) {

        def prefix = params.parentId.substring(0, params.parentId.indexOf('_') + 1)
        def parentID = params.parentId.substring(params.parentId.indexOf('_') + 1)
        def objectToAdd = null
        def nodePrefix = ''
        def objectIcon = null

        switch (prefix) {
            case PROJECT_ID_PREFIX:
                def objectParentFound = Project.get(parentID as Long)
                if (objectParentFound != null) {
                    objectToAdd = new Human()

                    objectParentFound.addToPeople(objectToAdd)
                    saveHuman(objectToAdd, params)

                    nodePrefix = HUMAN_ID_PREFIX
                    objectIcon = HUMAN_ICON
                }
                break

            case DEPARTMENT_ID_PREFIX:
                def objectParentFound = Department.get(parentID as Long)
                if (objectParentFound != null) {
                    objectToAdd = new Project()
                    objectParentFound.addToProjects(objectToAdd)
                    saveProject(objectToAdd, params)
                    nodePrefix = PROJECT_ID_PREFIX
                    objectIcon = PROJECT_ICON
                }
                break

            case ORGANIZATION_ID_PREFIX:
                objectToAdd = new Department()
                saveDepartment(objectToAdd, params)
                nodePrefix = DEPARTMENT_ID_PREFIX
                objectIcon = DEPARTMENT_ICON
                break
        }
        if (objectToAdd.hasErrors()) {
            return [success: false, errors: getErrorMessage(objectToAdd), msg: getFailureMessage()]
        } else {
            return [success: true, id: nodePrefix + objectToAdd.id, iconCls: objectIcon, name: objectToAdd.name, msg: getSuccessMessage()]
        }
    }

    def deleteNode(params) {
        def objectFound = getNodeInDatabase(params)
        if (objectFound != null) {
            objectFound.delete()
        }
        return [success: true]
    }

    def updateNodeName(params) {
        def objectFound = getNodeInDatabase(params)

        if (!objectFound) {
            return [success: false]
        } else {
            objectFound.name = params.newName
            objectFound.validate()
            if (objectFound.hasErrors()) {
                objectFound.discard()
                return [success: false, msg: getFailureMessage()]
            } else {
                objectFound.save(flush: true)
                return [success: true]
            }
        }
    }


    def loadNodeData(params) {
        def idString = params.id
        def prefix = idString.substring(0, idString.indexOf('_') + 1)
        def receivedId = idString.substring(idString.indexOf('_') + 1)

        switch (prefix) {

            case HUMAN_ID_PREFIX:
                def humanFound = Human.get(receivedId as Long)
                def dateToSend = !humanFound.dateHired ? null : humanFound.dateHired.format('MM/dd/yyyy')
                return [success: true, data: [name: humanFound.name, id: prefix + humanFound.id,
                        age: humanFound.age, salary: humanFound.salary, gender: humanFound.gender,
                        position: humanFound.position, humanEmail: humanFound.humanEmail, dateHired: dateToSend]]

//                def humanProperties = humanFound.properties
//                humanProperties['id'] = prefix + humanFound.id
//                humanProperties.put('dateHired', dateToSend)
//                return [success: true, data: [humanProperties ] ]

            case PROJECT_ID_PREFIX:
                def projectFound = Project.get(receivedId as Long)
                return [success: true, data: [name: projectFound.name, id: prefix + projectFound.id]]

//               def projectProperties= projectFound.properties
//                projectProperties['id']= prefix + projectFound.id
//                return [success: true, data: [projectProperties]]


            case DEPARTMENT_ID_PREFIX:
                def departmentFound = Department.get(receivedId as Long)
                return [success: true, data: [name: departmentFound.name, id: prefix + departmentFound.id]]

//                def departmentProperties= departmentFound.properties
//                departmentProperties['id']= prefix + departmentFound.id
//                return [success: true, data: [departmentProperties= departmentFound.properties]]

        }

    }

//    def SaveOrAddNode(params) {
//        boolean isNewNode
//        def idString
//
//        if (params.id) {
//            idString = params.id
//            isNewNode = false
//        } else {
//            isNewNode = true
//            idString = params.parentId
//        }
//
//        def prefix = idString.substring(0, idString.indexOf('_') + 1)
//        def receivedId = idString.substring(idString.indexOf('_') + 1)
//
//        def objectFound = null
//
//        def nodePrefix = ''
//        def objectIcon = null
//
//        switch (prefix) {
//
//            case HUMAN_ID_PREFIX:
//                objectFound = Human.get(receivedId as Long)
//                if (objectFound) {
//                    saveHuman(objectFound, params)
//                }
//                break
//
//            case PROJECT_ID_PREFIX:
//
//                if (isNewNode) {
//                    def objectParentFound = Project.get(receivedId as Long)
//                    if (!objectParentFound) {
//                        return
//                    }
//
//                    objectFound = new Human()
//                    objectParentFound.addToPeople(objectFound)
//
//                    nodePrefix = HUMAN_ID_PREFIX
//                    objectIcon = HUMAN_ICON
//
//                } else {
//                    objectFound = Human.get(receivedId as Long)
//
//                    if (!objectFound) {
//                        return
//                    }
//                }
//
//                saveHuman(objectFound, params)
//
//                break
//
//            case DEPARTMENT_ID_PREFIX:
//
//                if (isNewNode) {
//                    def objectParentFound = Department.get(receivedId as Long)
//                    if (!objectParentFound) {
//                        return
//                    }
//
//                    objectFound = new Project()
//                    objectParentFound.addToProjects(objectFound)
//
//                    nodePrefix = PROJECT_ID_PREFIX
//                    objectIcon = PROJECT_ICON
//
//                }else{
//                    objectFound = Department.get(receivedId as Long)
//                    if (!objectFound) {
//                        return
//                    }
//                }
//                saveProject(objectFound, params)
//
//                break
//
//            case ORGANIZATION_ID_PREFIX:
//                objectFound = new Department()
//                saveDepartment(objectFound, params)
//                nodePrefix = DEPARTMENT_ID_PREFIX
//                objectIcon = DEPARTMENT_ICON
//                break
//        }
//    }

}
